//enumeration of supported map types
var MapTypes = {
    ROADMAP:   0,
    SATELLITE: 1,
    HYBRID:    2
};

//class incapsulating geo coordinates
function Coords(Latitude, Longitude){
    this.latitude  = Latitude;
    this.longitude = Longitude;
};

//class incapsulating work with native place marks
function PlaceMark(coords, hint, onclick, id){
    this.coordinates = coords;
    this.hintMessage = hint;
    this.onclick     = onclick;
    this.id          = id;
};

//abstract interface for maps
function IMap() {
    var self = this;
    var nativePlaceMarks        = undefined;
    var placeMarks              = undefined;
    this.initMap                = undefined;
    this.getCenter              = undefined;
    this.setCenter              = undefined;
    this.getZoom                = undefined;
    this.setZoom                = undefined;
    this.getMapType             = undefined;
    this.setMapType             = undefined;
    this.addPlaceMark           = undefined;
    this.getAllPlaceMarks       = undefined;
    this.getNativePlaceMarks    = undefined;
    this.filterPlaceMarksByIds  = undefined;
    this.showAllPlaceMarks      = undefined;
}

//map factory
var MapEngines = {
    Google: GoogleMap,
    // Yandex: YandexMap
};

//realisaton of IMap interface for Google maps
function GoogleMap() {
    var map = new IMap();
    map.initMap = function(parentElementId, mapType, center, zoomNumber ){
        var mapOptions = {
            panControl         : false,
            zoomControl        : true,
            mapTypeControl     : false,
            scaleControl       : true,
            streetViewControl  : false,
            overviewMapControl : true,
            }
        map.googleMap = new google.maps.Map(document.getElementById(parentElementId),
                                            mapOptions);
        map.googleMap.setZoom(zoomNumber);
        map.googleMap.setCenter(new google.maps.LatLng(center.latitude, center.longitude));
        switch(mapType){
            case MapTypes.ROADMAP:
                map.googleMap.setMapTypeId( google.maps.MapTypeId.ROADMAP );
                break;
            case MapTypes.SATELLITE:
                map.googleMap.setMapTypeId( google.maps.MapTypeId.SATELLITE );
                break;
            case MapTypes.HYBRID:
                map.googleMap.setMapTypeId( google.maps.MapTypeId.HYBRID );
                break;
            default:
                map.googleMap.setMapTypeId( google.maps.MapTypeId.ROADMAP );
                break;
        };
    };
    map.getCenter = function() {
        var center = map.googleMap.getCenter();
        return new Coords( center.lat(), center.lng() );
    };
    map.setCenter = function(coords) {
        map.googleMap.setCenter(new google.maps.LatLng(coords.latitude, coords.longitude));
    };
    map.getZoom = function() {
        map.googleMap.getZoom();
    };
    map.setZoom = function(zoomNumber) {
        map.googleMap.setZoom(zoomNumber);
    };
    map.getMapType = function() {
        switch(map.googleMap.getMapTypeId()){
            case google.maps.MapTypeId.ROADMAP:
                return MapTypes.ROADMAP;
            case google.maps.MapTypeId.SATELLITE:
                return MapTypes.SATELLITE;
            case google.maps.MapTypeId.HYBRID:
                return MapTypes.HYBRID;
            default:
                return MapTypes.ROADMAP;
        };
    };
    map.setMapType = function(mapType){
        switch(mapType){
            case MapTypes.ROADMAP:
                map.googleMap.setMapTypeId( google.maps.MapTypeId.ROADMAP );
                break;
            case MapTypes.SATELLITE:
                map.googleMap.setMapTypeId( google.maps.MapTypeId.SATELLITE );
                break;
            case MapTypes.HYBRID:
                map.googleMap.setMapTypeId( google.maps.MapTypeId.HYBRID );
                break;
            default:
                map.googleMap.setMapTypeId( google.maps.MapTypeId.ROADMAP );
                break;
        };
    };
    placeMarks       = new Array();
    nativePlaceMarks = new Array();
    map.addPlaceMark = function(newPlaceMark){
        placeMarks.push(newPlaceMark);
        var tempGooglePlaceMark = new google.maps.Marker({
            position: new google.maps.LatLng(newPlaceMark.coordinates.latitude, newPlaceMark.coordinates.longitude),
            map: map.googleMap,
            title: newPlaceMark.hintMessage
        });
        nativePlaceMarks.push(tempGooglePlaceMark);
        google.maps.event.addListener(nativePlaceMarks[nativePlaceMarks.length-1], 'click', newPlaceMark.onclick);
    };
    map.getAllPlaceMarks = function(){
        return placeMarks;
    };
    map.getNativePlaceMarks = function(){
        return nativePlaceMarks;
    };
    map.filterPlaceMarksByIds = function(ids){
        for(var i=0; i<placeMarks.length; i++){
            var match = false;
            for(var j=0; j<ids.length; j++){
                if(placeMarks[i].id == ids[j]){
                    match = true;
                };
            };
            if(!match){
                nativePlaceMarks[i].setMap(null);
            };
        };
    };
    map.showAllPlaceMarks = function(){
        for(var i=0; i<nativePlaceMarks.length; i++){
            nativePlaceMarks[i].setMap(map.googleMap);
        };
    };
    return map;
};

// //realisaton of IMap interface for Yandex maps
// function YandexMap(){
//     var map = new IMap();
//     map.initMap = function(parentElementId, mapType, center, zoomNumber ){
//         var options = {
//             center: [center.latitude, center.longitude],
//             zoom:   zoomNumber
//         };
//         var type;
        
//         switch(mapType){
//             case MapTypes.ROADMAP:
//                 type = ymaps.MapType.MAP;
//                 break;
//             case MapTypes.SATELLITE:
//                 type = ymaps.MapType.SATELLITE;
//                 break;
//             case MapTypes.HYBRID:
//                 type = ymaps.MapType.HYBRID;
//                 break;
//             default:
//                 type = ymaps.MapType.MAP;
//                 break;
//         };
        
//         options.type = type;
        
//         map.yandexMap = new ymaps.Map(parentElementId, options);
//         map.yandexMap.controls.add('zoomControl');
//         map.yandexMap.controls.add('mapTools');
//     };
//     map.getCenter = function() {
//         var center = map.yandexMap.getCenter();
//         return new Coords( center[0], center[1] );
//     };
//     map.setCenter = function(coords) {
//         map.yandexMap.setCenter( [ coords.latitude, coords.longitude ] );
//     };
//     map.getZoom = function() {
//         return map.yandexMap.getZoom();
//     };
//     map.setZoom = function(zoomNumber) {
//         map.yandexMap.setZoom( zoomNumber, null );
//     };
//     map.getMapType = function() {
//         switch( map.yandexMap.getType() ){
//             case ymaps.MapType.MAP:
//                 return MapTypes.ROADMAP;
//             case ymaps.MapType.SATELLITE:
//                 return MapTypes.SATELLITE;
//             case ymaps.MapType.HYBRID:
//                 return MapTypes.HYBRID;
//             default:
//                 return MapTypes.ROADMAP;
//         };
//     };
//     map.setMapType = function(mapType){
//         switch(mapType){
//             case MapTypes.ROADMAP:
//                 map.yandexMap.setType( ymaps.MapType.MAP );
//                 break;
//             case MapTypes.SATELLITE:
//                 map.yandexMap.setType( ymaps.MapType.SATELLITE );
//                 break;
//             case MapTypes.HYBRID:
//                 map.yandexMap.setType( ymaps.MapType.HYBRID );
//                 break;
//             default:
//                 map.yandexMap.setType( ymaps.MapType.MAP );
//                 break;
//         };
//     };
//     placeMarks       = new Array();
//     nativePlaceMarks = new Array();
//     map.addPlaceMark = function(newPlaceMark){
//         placeMarks.push(newPlaceMark);
//         var tempYandexPlaceMark = new ymaps.Placemark([newPlaceMark.coordinates.latitude, newPlaceMark.coordinates.longitude], {hintContent: newPlaceMark.hintMessage});
//         nativePlaceMarks.push(tempYandexPlaceMark);
//         map.yandexMap.geoObjects.add(tempYandexPlaceMark);
//         // TODO: add click support
//     };
//     map.getAllPlaceMarks = function(){
//         return placeMarks;
//     };
//     map.getNativePlaceMarks = function(){
//         return nativePlaceMarks;
//     }
//     return map;
// };
